package Controller

import (
	"bytes"
	"context"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"gopkg.in/ini.v1"
	"io"
	"log"
	"math"
	"net/http"
	"strconv"
	"time"
	"web_back_go/Common"
	"web_back_go/DAO/gorm"
	"web_back_go/DAO/gorm/GormModel"
	"web_back_go/Response"
)

// prodCommDataDto 商品评论数据
type prodCommDataDto struct {
	PositiveRating  float64 `json:"positiveRating"`  // 对应好评率
	Number          int     `json:"number"`          // 评论数量
	PraiseNumber    int     `json:"praiseNumber"`    // 好评数
	SecondaryNumber int     `json:"secondaryNumber"` // 中评数
	NegativeNumber  int     `json:"negativeNumber"`  // 差评数
	PicNumber       int     `json:"picNumber"`       // 有图数
}

// prodCommDto 商品评论
type prodCommDto struct {
	ProdCommId   int64     `json:"prodCommId"`   // 对应id
	Score        int       `json:"score"`        // 得分，0-5分
	IsAnonymous  int       `json:"isAnonymous"`  // 是否匿名(1:是  0:否)
	ReplyContent string    `json:"replyContent"` // 掌柜回复
	RecTime      time.Time `json:"recTime"`      // 记录时间
	ReplyTime    time.Time `json:"replyTime"`    // 回复时间
	NickName     string    `json:"nickName"`     // 用户昵称
	Pic          string    `json:"pic"`          // 头像图片路径
	ReplySts     int       `json:"replySts"`     // 是否回复 0:未回复  1:已回复
	Pics         string    `json:"pics"`         // 评论图片
	Evaluate     byte      `json:"evaluate"`     // 评价等级（0好评 1中评 2差评）
	Content      string    `json:"content"`      // 评论内容
}

type ProdCommParam struct {
	// 商品id
	ProdID *int64 `json:"prodId" `
	// 订单项ID
	OrderItemID *int64 `json:"orderItemId" `
	// 评价，0-5分
	Score *int `json:"score" `
	// 评论内容
	Content *string `json:"content" `
	// 评论图片, 用逗号分隔
	Pics *string `json:"pics"`
	// 是否匿名(1:是  0:否) 默认为否
	IsAnonymous *int `json:"isAnonymous"`
	// 评价(0好评 1中评 2差评)
	Evaluate *int `json:"evaluate"`
}
type EvaluateInfo struct {
	Content  string `json:"content"`
	Evaluate int    `json:"evaluate"`

	IsAnonymous bool `json:"isAnonymous"`

	Pics     string `json:"pics"`
	ProdId   int    `json:"prodId"`
	Score    int    `json:"score"`
	OrderNum string `json:"ordernum" `
}

/*
GetProdCommDataById
@Description: 获取商品评论数据
*/
func GetProdCommDataById(c *gin.Context) {
	prodId := c.Query("prodId")
	var db = gorm.Db
	var prodCommDataDto prodCommDataDto

	result := db.Raw(`
        SELECT count(1)                                               AS number,
               count(CASE WHEN evaluate = 0 THEN 1 END)               AS praise_number,
               count(CASE WHEN evaluate = 1 THEN 1 END)               AS secondary_number,
               count(CASE WHEN evaluate = 2 THEN 1 END)               AS negative_number,
               count(CASE WHEN pics IS NOT NULL THEN 1 END)           AS pic_number
        FROM tz_prod_comm
        WHERE prod_id = ? AND status = 1
    `, prodId).Scan(&prodCommDataDto)

	if prodCommDataDto.PraiseNumber == 0 || prodCommDataDto.Number == 0 {
		prodCommDataDto.PositiveRating = 0.0
	} else {
		prodCommDataDto.PositiveRating = float64(prodCommDataDto.PraiseNumber) / float64(prodCommDataDto.Number) * 100
	}

	if result.Error != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A0001",
			Data:      prodCommDataDto,
			Fail:      true,
			Msg:       "获取商品评论数据失败",
			Sign:      "",
			Success:   false,
			Timestamp: time.Now().Unix(),
			Version:   "V1.0",
		})
		return
	}

	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      prodCommDataDto,
		Fail:      false,
		Msg:       "获取商品评论数据成功",
		Sign:      nil,
		Success:   true,
		Timestamp: time.Now().Unix(),
		Version:   "V1.0",
	})
}

/*
GetProdCommPageByProdId
@Description: 获取商品评论分页数据
*/
func GetProdCommPageByProdId(c *gin.Context) {
	prodId := c.Query("prodId")
	currentStr := c.Query("current")
	sizeStr := c.Query("size")
	evaluateStr := c.Query("evaluate")

	page, err := strconv.Atoi(currentStr)
	if err != nil || page < 1 {
		page = 1
	}

	size, err := strconv.Atoi(sizeStr)
	if err != nil || size < 1 {
		size = 10
	}

	evaluate, err := strconv.Atoi(evaluateStr)
	if err != nil {
		evaluate = -1
	}

	var db = gorm.Db
	var prodCommList []prodCommDto

	query := db.Table("tz_prod_comm pc").
		Select("pc.prod_comm_id, pc.score, pc.is_anonymous, pc.reply_content, pc.rec_time, pc.reply_time, pc.reply_sts, pc.pics, pc.evaluate, pc.content, u.nick_name, u.pic").
		Joins("left join tz_user u on u.user_id = pc.user_id").
		Where("pc.prod_id = ? and pc.status = 1", prodId)

	if evaluate != -1 && evaluate != 3 {
		query = query.Where("pc.evaluate = ?", evaluate)
	} else if evaluate == 3 {
		query = query.Where("pc.pics is not null")
	}

	// 获取分页数据
	var count int64
	result := query.Count(&count).Offset((page - 1) * size).Limit(size).Find(&prodCommList)

	if result.Error != nil {
		log.Println(result.Error)
		c.JSON(200, Response.ResponseBody{
			Code:      "A0001",
			Data:      nil,
			Fail:      true,
			Msg:       "获取商品评论分页数据失败",
			Sign:      "",
			Success:   false,
			Timestamp: time.Now().Unix(),
			Version:   "V1.0",
		})
		return
	}

	// 构造响应
	c.JSON(200, Response.ResponseBody{
		Code: "00000",
		Data: Common.PageParam1[prodCommDto]{
			Current: page,
			Total:   count,
			Size:    size,
			Records: prodCommList,
			Pages:   int(math.Ceil(float64(count) / float64(size))),
		},
		Fail:      false,
		Msg:       nil,
		Sign:      nil,
		Success:   true,
		Timestamp: time.Now().Unix(),
		Version:   "V1.0",
	})
}

/*
GetUserCommonPage
@Description: 根据用户返回评论分页数据
*/
func GetUserCommonPage(c *gin.Context) {
	currentStr := c.Query("current")
	sizeStr := c.Query("size")

	page, err := strconv.Atoi(currentStr)
	if err != nil || page < 1 {
		page = 1 // 默认第一页
	}

	size, err := strconv.Atoi(sizeStr)
	if err != nil || size < 1 {
		size = 10 // 默认每页10条
	}

	// 计算分页偏移量
	offset := (page - 1) * size
	userId, _ := Common.GetUserId(c)
	log.Printf("获取的userId", userId)
	db := gorm.Db

	var total int64
	countQuery := db.Model(&GormModel.TzProdComm{}).
		Where(&GormModel.TzProdComm{UserID: userId})

	if err := countQuery.Count(&total).Error; err != nil {

		c.JSON(200, Response.ResponseBody{
			Code:    "A0001",
			Msg:     nil,
			Data:    nil,
			Version: "V1.0",
			Sign:    nil,
			Success: true,
			Fail:    false,
		})
		return
	}

	// 分页查询数据
	var prodComm []GormModel.TzProdComm
	dataQuery := db.
		Where(&GormModel.TzProdComm{UserID: userId}).
		Order("rec_time DESC") // 按时间倒序

	if err := dataQuery.Offset(offset).Limit(size).Find(&prodComm).Error; err != nil {

		c.JSON(200, Response.ResponseBody{
			Code:      "A0001",
			Data:      nil,
			Fail:      true,
			Msg:       "获取商品评论分页数据失败",
			Sign:      "",
			Success:   false,
			Timestamp: time.Now().Unix(),
			Version:   "V1.0",
		})
		return
	}

	// 构造响应数据
	c.JSON(200, Response.ResponseBody{
		Code: "00000",
		Data: Common.PageParam1[GormModel.TzPickAddr]{
			Current: currentStr,
			Total:   total,
			Size:    size,
			Records: prodComm,
			Pages:   int(math.Ceil(float64(total) / float64(size))),
		},
		Msg:       nil,
		Success:   true,
		Fail:      false,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
	})
}

/*
DeleteProdComm
@Description: 删除评论
*/
func DeleteProdComm(c *gin.Context) {
	prodCommIdStr := c.Param("prodCommId")
	prodCommId, err := strconv.ParseInt(prodCommIdStr, 10, 64)
	db := gorm.Db.Begin()
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()

	db.Delete(&GormModel.TzProdComm{}, "prod_comm_id = ?", prodCommId)

	c.JSON(200, Response.ResponseBody{
		Code:    "00000",
		Data:    nil,
		Success: true,
		Msg:     "删除成功",
	})
}

/*
AddProdCommPage
添加评论
*/
func AddProdCommPage(c *gin.Context) {
	var evaluateInfo []EvaluateInfo
	clientIP := c.ClientIP()
	if err := c.ShouldBindJSON(&evaluateInfo); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:    "A00001",
			Data:    nil,
			Success: true,
			Msg:     "参数错误",
			Sign:    nil,
			Version: "V1.0.0",
		})
		return
	}

	userId, err := Common.GetUserId(c)
	db := gorm.Db.Begin()
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	for _, info := range evaluateInfo {
		var prodComm GormModel.TzProdComm
		var orderItem GormModel.TzOrderItem

		//orderNumber, _ := strconv.ParseUint(info.OrderNum, 10, 64)
		db.Where("order_number = ?", info.OrderNum).First(&orderItem)
		prodComm.UserID = userId
		prodComm.OrderItemID = orderItem.OrderItemID
		prodComm.Score = int8(info.Score)
		prodComm.Content = info.Content
		prodComm.Pics = info.Pics
		prodComm.ProdID = orderItem.ProdID
		if info.IsAnonymous {
			prodComm.IsAnonymous = 1
		} else {
			prodComm.IsAnonymous = 0
		}
		prodComm.Postip = clientIP
		prodComm.RecTime = Common.GetCurrentTime()
		prodComm.Status = 0
		prodComm.Evaluate = int8(info.Evaluate)
		prodComm.ReplyTime = time.Now()

		db.Save(&prodComm)
		//将订单项也更新
		db.Model(&GormModel.TzOrderItem{}).
			Where("order_item_id = ?", prodComm.OrderItemID).
			Update("comm_sts", 1)
		var updatedItem GormModel.TzOrderItem
		db.Where("order_item_id = ?", prodComm.OrderItemID).First(&updatedItem)

		//订单也更新
		db.Model(&GormModel.TzOrder{}).Where("order_number = ?", updatedItem.OrderNumber).Update("status", Common.SUCCESS.Value())
		//区块链也更新
		cfg, _ := ini.Load("./Config/config.ini")
		enabled := cfg.Section("blockchain").Key("enabled").String()
		url := cfg.Section("blockchain").Key("url").String()
		if enabled == "true" {

			go func() {
				// 安全构造 JSON
				reqBody, _ := json.Marshal(map[string]string{
					"orderNumber": updatedItem.OrderNumber,
				})

				// 添加上下文超时
				ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
				defer cancel()

				// 创建 HTTP 请求
				req, _ := http.NewRequestWithContext(ctx, "POST", url+"/OrderCommon",
					bytes.NewBuffer(reqBody))
				req.Header.Set("Content-Type", "application/json")

				// 发送请求
				resp, err := http.DefaultClient.Do(req)
				if err != nil {
					log.Printf("请求失败: %v", err)
					return
				}
				defer resp.Body.Close()

				// 处理非 200 状态码
				if resp.StatusCode != http.StatusOK {
					body, _ := io.ReadAll(resp.Body)
					log.Printf("操作失败: 状态码=%d, 响应=%s", resp.StatusCode, string(body))
					return
				}

				// 处理成功响应
				var result map[string]interface{}
				if err := json.NewDecoder(resp.Body).Decode(&result); err == nil {
					log.Printf("操作成功: %+v", result)
				}
			}()
		}

		c.JSON(200, Response.ResponseBody{
			Code:    "00000",
			Data:    nil,
			Success: true,
			Msg:     nil,
		})
	}
}
